package logic

import (
	"context"
	"demo_srv/global"
	"demo_srv/inventory_proto"
	"demo_srv/model"
	"github.com/go-redsync/redsync/v4"
	"github.com/go-redsync/redsync/v4/redis/goredis/v9"
	goredislib "github.com/redis/go-redis/v9"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"time"
)

// 添加商品库存
func (s *Server) SetInv(ctx context.Context, in *inventory_proto.GoodsInvInfo) (*inventory_proto.Empty, error) {
	var inv model.Inventory
	global.DB.Where(&model.Inventory{GoodsId: in.GoodsID}).Find(&inv)
	inv.GoodsId = in.GoodsID
	inv.Stock = in.Nums
	tx := global.DB.Save(&inv)
	if tx.Error != nil {
		return nil, status.Errorf(codes.Internal, "添加库存失败")
	}
	return &inventory_proto.Empty{}, nil
}

// 查询库存详情
func (s *Server) InvDetail(ctx context.Context, in *inventory_proto.GoodsInvInfo) (*inventory_proto.GoodsInvInfo, error) {
	var inv model.Inventory
	tx := global.DB.Where(&model.Inventory{GoodsId: in.GoodsID}).First(&inv)
	if tx.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "查询详情失败")
	}
	return &inventory_proto.GoodsInvInfo{
		GoodsID: inv.GoodsId,
		Nums:    inv.Stock,
	}, nil
}

// 扣减库存
func (s *Server) Sell(ctx context.Context, in *inventory_proto.SellInfo) (*inventory_proto.Empty, error) {
	client := goredislib.NewClient(&goredislib.Options{
		Addr: "127.0.0.1:6379",
	})
	pool := goredis.NewPool(client)
	rs := redsync.New(pool)
	mutexName := "inventory-mutex"
	mutex := rs.NewMutex(mutexName, redsync.WithExpiry(10*time.Second), redsync.WithTries(5))
	if err := mutex.LockContext(ctx); err != nil {
		return nil, status.Errorf(codes.Internal, "获取redis锁失败")
	}
	tx := global.DB.Begin()
	for _, v := range in.GoodsInfo {
		var inv model.Inventory
		result := tx.Where(&model.Inventory{GoodsId: v.GoodsID}).First(&inv)
		if result.RowsAffected == 0 {
			tx.Rollback()
			return nil, status.Errorf(codes.NotFound, "无库存信息")
		}
		if inv.Stock < v.Nums {
			tx.Rollback()
			return nil, status.Errorf(codes.Internal, "库存不足")
		}
		inv.Stock -= v.Nums
		res := tx.Save(&inv)
		if res.Error != nil {
			tx.Rollback()
			return nil, status.Errorf(codes.Internal, "更新库存失败")
		}
	}
	tx.Commit()
	if ok, err := mutex.UnlockContext(ctx); !ok || err != nil {
		return nil, status.Errorf(codes.Internal, "释放redis锁失败")
	}
	return &inventory_proto.Empty{}, nil
}
func (s *Server) ReBack(ctx context.Context, in *inventory_proto.SellInfo) (*inventory_proto.Empty, error) {
	return &inventory_proto.Empty{}, nil
}
